package net.wanho.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import net.wanho.common.AuthConstant;
import net.wanho.common.UserConstant;
import net.wanho.mapper.AuthInfoMapper;
import net.wanho.mapper.RoleAuthMapper;
import net.wanho.po.AuthInfo;
import net.wanho.po.RoleAuth;
import net.wanho.service.AuthInfoService;
import net.wanho.util.CurrentUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 32033
 * @description 针对表【auth_info(权限表)】的数据库操作Service实现
 * @createDate 2025-01-11 17:01:23
 */
@Service
@RequiredArgsConstructor
public class AuthInfoServiceImpl extends ServiceImpl<AuthInfoMapper, AuthInfo>
        implements AuthInfoService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final RoleAuthMapper roleAuthMapper;
    private final AuthInfoMapper authInfoMapper;


    @Override
    public List<AuthInfo> getMenu() {
//        和Integer userId = CurrentUtil.getId()一样的效果;
//        Integer userId = (Integer)redisTemplate.opsForValue().get("token");

//        Integer userId = CurrentUtil.getId();
//        List<AuthInfo> menus = (List<AuthInfo>) redisTemplate.opsForValue().get(UserConstant.MENU_PREFIX + userId);
//        if (!CollectionUtils.isEmpty(menus)) {
//            return menus;
//        }
//        //获取当前用户所有权限
//        List<AuthInfo> authInfos = authInfoMapper.selectAllAuth(); // TODO 这个查询似乎有问题
//        menus = Optional.ofNullable(authInfos).orElse(new ArrayList<>()).stream()
//                .filter(item -> item.getParentId() == 0)
//                .map(item -> {
//                    findChildren(item, authInfos); // TODO 或许这里有问题
//                    return item;
//                }).collect(Collectors.toList());
//        redisTemplate.opsForValue().set(UserConstant.MENU_PREFIX + userId, menus, UserConstant.MENU_EXPIRE, UserConstant.MENU_EXPIRE_UNIT);
//        return menus;


        Integer userId = CurrentUtil.getId();

        // 从缓存中获取权限树
        List<AuthInfo> list = (List<AuthInfo>) redisTemplate.opsForValue().get(UserConstant.MENU_PREFIX + userId);
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }

        // 查询所有启用的权限
        LambdaQueryWrapper<AuthInfo> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(AuthInfo::getAuthState, AuthConstant.AUTH_STATE_ENABLE);// 只查询启用的权限
        queryWrapper.orderByAsc(AuthInfo::getAuthOrder);// 按权限顺序升序排序

        List<AuthInfo> allAuth = baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(allAuth)) {
            return new ArrayList<>();
        }

        // 构建权限树
        list = allAuth.stream()
//        List<AuthInfo> list = allAuth.stream()
                .filter(auth -> auth.getParentId() == 0)// 过滤出一级权限
                .peek(auth -> {
                    // 设置子权限
                    List<AuthInfo> children = getChild(auth, allAuth);
                    auth.setChildAuth(children);
                })
                .collect(Collectors.toList());
        redisTemplate.opsForValue().set(UserConstant.MENU_PREFIX + userId, list, UserConstant.MENU_EXPIRE, UserConstant.MENU_EXPIRE_UNIT);
        return list;
    }

    private List<AuthInfo> getChild(AuthInfo parent, List<AuthInfo> allAuth) {
        return allAuth.stream()
                .filter(auth -> auth.getParentId().equals(parent.getAuthId()))// 过滤出子权限
                .peek(auth -> {
                    // 递归设置子权限
                    List<AuthInfo> children = getChild(auth, allAuth);
                    auth.setChildAuth(children);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Integer> findByUserId(Integer userId) {
        return authInfoMapper.findByUserId(userId);
    }

    @Override
    public Boolean findByAuthName(String authName) {
        AuthInfo authInfo = authInfoMapper.selectByAuthName(authName);
        if (authInfo != null)
            return false;
        return true;
    }

    @Override
    public Boolean findByAuthUrl(String authUrl) {
        AuthInfo authInfo = authInfoMapper.selectByAuthUrl(authUrl);
        if (authInfo != null)
            return false;
        return true;
    }

    @Override
    public Boolean findByAuthCode(String authCode) {
        AuthInfo authInfo = authInfoMapper.selectByAuthCode(authCode);
        if (authInfo != null)
            return false;
        return true;
    }

    @Override
    public void add(AuthInfo authInfo) {
        authInfo.setAuthState(AuthConstant.AUTH_STATE_ENABLE);
        authInfo.setCreateBy((Integer) redisTemplate.opsForValue().get("token"));
        authInfo.setCreateTime(new Date());
        redisTemplate.delete(UserConstant.MENU_PREFIX + redisTemplate.opsForValue().get("token"));
        this.save(authInfo);
    }

//    @Override
//    public List<AuthInfo> getAuthTree() {
//        List<AuthInfo> authInfoList = this.list();
//
//        List<AuthInfo> list = authInfoList.stream()
//                .filter(item -> item.getParentId() == 0)
//                .map(item -> {
//                    // 递归查询子权限
//                    findChildren(item, authInfoList);
//                    return item;
//                })
//                .collect(Collectors.toList());
//        return list;
//    }

    @Override
    public void authEnable(Integer id) {
        AuthInfo authInfo = new AuthInfo();
        authInfo.setAuthId(id);
        authInfo.setAuthState(AuthConstant.AUTH_STATE_ENABLE);
        this.updateById(authInfo);
        redisTemplate.delete(UserConstant.MENU_PREFIX + CurrentUtil.getId());
    }

    @Override
    public void authDisable(Integer id) {
        AuthInfo authInfo = new AuthInfo();
        authInfo.setAuthId(id);
        authInfo.setAuthState(AuthConstant.AUTH_STATE_DISABLE);
        this.updateById(authInfo);
        redisTemplate.delete(UserConstant.MENU_PREFIX + redisTemplate.opsForValue().get("token"));
    }

    @Override
    public void authDelete(Integer id) {
        //判断权限是否关联角色
        boolean exists = roleAuthMapper.exists(new LambdaQueryWrapper<RoleAuth>().eq(RoleAuth::getAuthId, id));
        if (exists) {
            throw new RuntimeException("该权限已被角色关联，无法删除！");
        }
        //查找当前权限及所有子权限
        List<Integer> deleteIds = new ArrayList<>();
        deleteIds.add(id);
        // 递归查询子权限的id
        findChildIds(id, deleteIds);
        //批量删除
        this.removeByIds(deleteIds);
    }

    @Override
    public void updateAuthInfo(AuthInfo authInfo) {
        this.updateById(authInfo);
        redisTemplate.delete(UserConstant.MENU_PREFIX + redisTemplate.opsForValue().get("token"));
    }

    private void findChildren(AuthInfo item, List<AuthInfo> authInfos) {
        List<AuthInfo> children = authInfos.stream()
                .filter(subItem -> subItem.getParentId().equals(item.getAuthId()))
                .map(subItem -> {
                    findChildren(subItem, authInfos);
                    return subItem;
                }).collect(Collectors.toList());
        item.setChildAuth(children);
    }

    //递归查询子权限的id
    private void findChildIds(Integer id, List<Integer> deleteIds) {
        List<AuthInfo> authInfoList = this.list(new LambdaQueryWrapper<AuthInfo>().eq(AuthInfo::getParentId, id));
        if (!CollectionUtils.isEmpty(authInfoList)) {
            authInfoList.forEach(item -> {
                deleteIds.add(item.getAuthId());
                findChildIds(item.getAuthId(), deleteIds);
            });
        }
    }

}




